package org.jeecg.modules.websocket;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.util.ApplicationContextUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.sggg.entity.SgMember;
import org.jeecg.modules.sggg.service.ISgMemberService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.thymeleaf.util.StringUtils;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import static org.jeecg.common.constant.CommonConstant.REDIS_MSG;
import static org.jeecg.common.constant.CommonConstant.REDIS_MSG_TIME;

@ServerEndpoint("/appletSocket/{send}/{recv}/{type}")
@Component
public class WebSocketServer {

    private static final ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();

    private String send;

    //实现服务器发送消息
    private static void sendMessage(String recv, String message) throws IOException {
        sessionPool.get(recv).getBasicRemote().sendText(message);
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("send") String send, @PathParam("recv") String recv, @PathParam("type") String type) throws IOException {
        this.send = send;
        sessionPool.put(send, session);


        RedisUtil redisUtil = (RedisUtil) ApplicationContextUtils.getBean("redisUtil");
        ISgMemberService memberService = (ISgMemberService) ApplicationContextUtils.getBean("memberServiceImpl");
        RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");

        //机构端连接
        if ("null".equals(recv)) {
            //获取所有的聊天用户对象
            Set<String> keys = redisTemplate.keys(("msg:" + REDIS_MSG + this.send + "&").concat("*"));
            assert keys != null;
            keys.forEach(s -> {
                SgMember sgMember = memberService.getById(s.substring(s.indexOf("&") + 1));
                //返回聊天用户信息
                try {
                    sendMessage(send, JSONObject.toJSONString(sgMember));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });

        } else {
            //获取用户端或机构端离线时收到的消息并发送
            if ("app".equals(type)) {
                List<Object> list = redisUtil.lGet("msg:" + REDIS_MSG + recv + "&" + send, 0, redisUtil.lGetListSize("msg:" + REDIS_MSG + recv + "&" + send));

                //用户端第一次连接，新用户
                if (!redisUtil.hasKey("msg:" + REDIS_MSG + recv + "&" + send) && sessionPool.containsKey(recv)) {
                    //发送新用户身份信息给机构端
                    sendMessage(recv, JSONObject.toJSONString(memberService.getById(send)));
                }
                preSend(list, send);
            } else {
                List<Object> list = redisUtil.lGet("msg:" + REDIS_MSG + send + "&" + recv, 0, redisUtil.lGetListSize("msg:" + REDIS_MSG + send + "&" + recv));
                preSend(list, send);
            }
        }
    }

    //发送离线消息
    private void preSend(List<Object> list, String send) throws IOException {
        for (Object o : list) {
            JSONObject jsonObject = JSON.parseObject(o.toString());
            sendMessage(send, jsonObject.toJSONString());
        }
    }

    @OnClose
    public void onClose() {
        sessionPool.remove(send);
    }

    @OnMessage
    public String onMessage(String message) throws IOException {

        RedisUtil redisUtil = (RedisUtil) ApplicationContextUtils.getBean("redisUtil");

        //解析发送的消息
        JSONObject jsonObject = JSON.parseObject(message);

        //获取接收方
        String recv = jsonObject.getString("recv");

        //判断接收方是否在线
        if (!StringUtils.isEmpty(recv) && sessionPool.containsKey(recv)) {

            //判断发送方身份
            if ("app".equals(jsonObject.getString("type"))) {
                redisUtil.lSet("msg:" + REDIS_MSG + recv + "&" + this.send, jsonObject.toJSONString(), REDIS_MSG_TIME);
            } else {
                redisUtil.lSet("msg:" + REDIS_MSG + this.send + "&" + recv, jsonObject.toJSONString(), REDIS_MSG_TIME);
            }
            //发送聊天消息
            sendMessage(recv, jsonObject.toJSONString());

        } else {
            //接收方不在线，只存储不发送
            if ("app".equals(jsonObject.getString("type"))) {
                redisUtil.lSet("msg:" + REDIS_MSG + recv + "&" + this.send, jsonObject.toJSONString(), REDIS_MSG_TIME);
            } else {
                redisUtil.lSet("msg:" + REDIS_MSG + this.send + "&" + recv, jsonObject.toJSONString(), REDIS_MSG_TIME);
            }
        }

        //返回刚发送的消息给发送方
        return String.valueOf(jsonObject);
    }

}
